package com.bardsoftware.foronuvolo.data;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.JDOCanRetryException;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Transaction;

import org.compass.core.Compass;
import org.compass.core.config.CompassConfiguration;
import org.compass.core.config.CompassEnvironment;
import org.compass.gps.CompassGps;
import org.compass.gps.device.jdo.Jdo2GpsDevice;
import org.compass.gps.impl.SingleCompassGps;

public class PMF {
    private static Logger LOGGER = Logger.getLogger(PMF.class.getName());
    private static final PersistenceManagerFactory ourFactory =
        JDOHelper.getPersistenceManagerFactory("transactions-optional");
    public static final Runnable JUST_PERSIST = new Runnable() {
        public void run() {
        }
    };

    private static Compass ourCompass;
    private static CompassGps ourCompassGps;

    static {
        ourCompass = new CompassConfiguration()
        .setConnection("gae://index")
        .setSetting(CompassEnvironment.ExecutorManager.EXECUTOR_MANAGER_TYPE, "disabled")
        .addScan("com.bardsoftware.foronuvolo.data")
        .buildCompass();
    ourCompassGps = new SingleCompassGps(ourCompass);
    Jdo2GpsDevice jdo2GpsDevice = new Jdo2GpsDevice("appengine", ourFactory);
    jdo2GpsDevice.setMirrorDataChanges(false);
    ourCompassGps.addGpsDevice(jdo2GpsDevice);
    if (ourCompass.getSearchEngineIndexManager().isLocked()) {
        ourCompass.getSearchEngineIndexManager().releaseLocks();
    }
    ourCompassGps.start();
    }
    public static PersistenceManagerFactory getFactory() {
        return ourFactory;
    }

    public static boolean runInTransaction(PersistenceManager pm, Object o, Runnable r, int retries) {
        for (int i = 0; i < retries; i++) {
            Transaction tx = pm.currentTransaction();
            try {
                tx.begin();
                pm.setDetachAllOnCommit(true);
                r.run();
                if (o != null) {
                    pm.makePersistent(o);
                }
                tx.commit();
                return true;
            }
            catch (JDOCanRetryException e) {
                if (i == retries - 1) {
                    return false;
                }
            }
            catch (Throwable e) {
                LOGGER.log(Level.WARNING, "Attempt#"+i+" failed: "+e.getMessage(), e);
                return false;
            }
            finally {
                if (tx.isActive()) {
                    tx.rollback();
                }
            }
        }
        return false;
    }
    public static boolean runInTransaction(Object o, Runnable r, int retries) {
        PersistenceManager pm = getFactory().getPersistenceManager();
        try {
            return runInTransaction(pm, o, r, retries);
        }
        finally {
            pm.close();
        }
    }
    public static Compass getCompass() {
//        if (ourCompass == null) {
//        }
        return ourCompass;
    }
}
